package com.chen.aspect;

import cn.hutool.core.lang.Snowflake;
import com.chen.ann.RequestType;
import com.chen.domain.SysUserLog;
import com.chen.enums.RequestTypeEnum;
import com.chen.service.SysUserLogService;
import com.chen.utils.IpUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Author: chen
 * @Date: 2021/4/16 10:03 AM
 * @Version 1.0
 */
@Aspect
@Order(2)
@Component
@Slf4j
public class WebAdminLogAspect {

    private static final String defDescription = "该方法没有描述";
    private static final Long defUserId = 0L;

    //雪花算法，用来生成id
    private Snowflake snowflake = new Snowflake(1, 1);

    @Autowired
    private SysUserLogService sysUserLogService;

    //切面表达式
    @Pointcut("execution(* com.chen.controller.*.*(..))")
    public void setWebLogAspectPotcut() {

    }

    //ProceedingJoinPoint 这个是就代表目标方法
    @Around(value = "setWebLogAspectPotcut()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        SysUserLog sysUserLog = new SysUserLog();

        //获取执行方法的实例
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();

        //过去方法上的注解
        ApiOperation annotation = method.getAnnotation(ApiOperation.class);
        RequestType requestType = method.getAnnotation(RequestType.class);

        //设置自定义注解上的值
        if (requestType == null) {
            sysUserLog.setGroup(RequestTypeEnum.DEFAULT.getMsg());
        } else {
            sysUserLog.setGroup(requestType.value().getMsg());
        }

        //设置方法的描述
        if (annotation == null) {
            sysUserLog.setDescription(defDescription);
        } else {
            String value = annotation.value();
            sysUserLog.setDescription(StringUtils.isBlank(value) ? defDescription : value);
        }

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //设置用户
        Long userId;
        try {
            //注意：如果未登录 userId 将不是long类型哦
            userId = Long.parseLong(authentication.getPrincipal().toString());
        } catch (Exception e) {
            userId = defUserId;
        }

        sysUserLog.setId(userId);

        //设置方法的消耗时间
        Object result = null;
        StopWatch stopWatch = new StopWatch(); // 创建计时器
        stopWatch.start(); //  开始计时器
        result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); // 不需要我们自己处理这个异常
        stopWatch.stop(); // 记时结束

        //设置方法的消耗时间
        sysUserLog.setTime(stopWatch.getTotalTimeMillis());

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        //获取请求request
        HttpServletRequest request = requestAttributes.getRequest();

        sysUserLog.setId(snowflake.nextId());
        sysUserLog.setIp(IpUtils.getIpAddr(request));
        sysUserLog.setMethod(request.getMethod());
        sysUserLog.setRemark(sysUserLog.getDescription());

        //保存日志到数据库
        sysUserLogService.save(sysUserLog);

        return result;

    }


}
